﻿#light

namespace CodeBlock.AMD64

module TypeResolver

open System
open System.Linq

open Mono.Cecil

type BaseAssemblyResolver with
    [<OverloadID("module")>]
    member private this.FindType(name, amodule: ModuleDefinition)=
        (amodule.Types.OfType<TypeDefinition>()).SingleOrDefault(fun t -> t.FullName = name)
    
    [<OverloadID("assembly")>]
    member private this.FindType(name, assembly: AssemblyDefinition) =
        let inModules = assembly.Modules.OfType<ModuleDefinition>() |> Seq.map (fun amodule -> this.FindType(name, amodule))
        inModules.Single(fun t -> t <> null)
    
    [<OverloadID("typeref")>]
    member this.ResolveType (refer: TypeReference)=
        match refer with
        | null -> raise(ArgumentNullException("refer"))
        | :? TypeDefinition -> refer :?> TypeDefinition
        | :? ArrayType ->
//            output {    Entry = NotImplementedException("array type resolving");
//                        Position = null, [] }
            failwith "fatal error: can't resolve array type"
        
        | _ when refer.GetType().Equals(typeof<TypeReference>) ->
            let assemblyName = refer.Scope :?> AssemblyNameReference
            let assembly = this.Resolve(assemblyName)
            this.FindType(refer.FullName, assembly)
        
        | _ ->
//            output {    Entry = NotImplementedException(sprintf "can't resolve type %s" refer.FullName);
//                        Position = null, [] }
            failwith (sprintf "fatal error: can't resolve type %A of type %A" refer (refer.GetType()))
